home *** CD-ROM | disk | FTP | other *** search
- Path: newspost1.alt.net!usenet
- From: walth@netcom.com (Walt Howard)
- Newsgroups: comp.lang.c++
- Subject: Re: Copy constructing an already default constructed object
- Date: Sun, 28 Jan 1996 12:58:44 GMT
- Organization: AltNet - Affordable Usenet Access - http://www.alt.net
- Message-ID: <4efruf$elb@tofu.alt.net>
- References: <4e906b$stk@elaine32.Stanford.EDU> <ENNO.96Jan26221035@kitz.inferenzsysteme.informatik.th-darmstadt.de>
- Reply-To: walth@netcom.com
- X-Newsreader: Forte Agent .99c/32.126
-
- On 26 Jan 1996 21:10:35 GMT,
- enno@inferenzsysteme.informatik.th-darmstadt.de (Enno Sandner) wrote:
-
- >In article <4e906b$stk@elaine32.Stanford.EDU> brien@leland.Stanford.EDU (brien oberstein) writes:
- >
- > I'd like to get some opinions on the best/cleanest way
- > to accomplish the following:
- >
- > I've got an object which has already been constructed
- > via its default constructor which just sets all pointers
- > to NULL. Whats the best way to deep-copy into it?
- >
- >
- > class A {
- > public:
- > A(); // default ctor
- > A(const A&) // copy ctor
- > A(const char *) // convert ctor
- > };
- >
- > somefunc()
- > {
- > ...
- > A a0;
- > ...
- > A a1("blah");
- >
- > //
- > // How do you deep copy a1 into a0 ???
- > //
- > a0 = a1; // no good. shallow copy
- > a0 = A(a1); // no good. dtor called for temp A object
- > a0 = *new A(a1); // no good. creates memory for a A object
- >
- > //
- > // the follow works but is tedious
- > //
- > A empty; // create an empty object
- > A tmp(a1); // deep-copy a1 to temp
-
- Here you are using a copy constructor. How is the copy constructor
- doing a deep copy? Use that logic here!
-
- > a0 = tmp; // shallow-copy temp to a0
- > tmp = empty; // clear out temp so internals are not destructed
- >
- > //
- > // so overload = to make deep copies
- > //
- > a0 = a1;
- >
- > }
- >
- > //
- > // deep-copy =
- > //
- > A& A::operator =(const A& other)
- > {
- > A empty;
- > A tmp(other);
- > memcpy(this, &tmp, sizeof(A));
- > memcpy(&tmp, &empty, sizeof(A));
- > return *this;
- > }
- >
- >
-
- One thing I do is to avoid unecessary pointers. For example so often
- the pointers point to strings or memory buffers you should just create
- a simple class of string and simple class of memory buffer that you
- put into the object so you don't have to have a pointer. Copy
- construction and assignment then work automatically.
-
- class NeedsCustomWrittenAssignmentOperator
- {
- char* contents;
- };
-
- class DefaultAssignmentOperatorWorksFine
- {
- memorybuffer contents; // (memory buffer is a class)
- };
-
- Because assignment of a whole object is done by assignment of its
- individual members, the second class doesn't need to have
- an assignment operator written.
-
- Now somewhere along the line you are going to have to deal with a
- pointer to a block of memory. That you do WITHIN the memorybuffer
- object and do it really well, ONCE AND FOR ALL. Now you can use that
- work you put into taming pointers without danger of making a mistake.
- You can use your brainpower on more important things.
-
- AND if you want the memorybuffer to LOOK like a memory buffer, you
- just declare an: operator char*() function that returns the actual
- memory address that memorybuffer is managing. It will look JUST like
- the old kind of malloc'ed memory, but has an object around it to deal
- with copying, construction and destruction.
-
- Pointers, though sometimes necessary, carry a HEAVY price. They
- introduce dependencies upon:
-
- 1) Memory layout
- 2) Referents - the pointer and the pointee are now bound together in
- an inflexible construct.
-
- which results in
-
- 3) The objects involved begin to act like ONE large object.
-
- and thus losing the flexibility you might have been trying to achieve
- by using objects.
-
- > I'd like to know what people think of the solution I've reached.
- > I figure that this type of shit is common enough so there should
- > be some widely accepted solution to this problem. Or maybe its
- > not, but believe me that the situation does occur.
- >
- >A class should define its copy-semantics, not the clients of that class.
- >Often assignment can be expressed in terms of destruction and copy-
- >construction, ie.
- >
- > Class& operator = (const Class& c) {
- > if (this!=&c) {
- > this->~Class(); // cleanup
- > new (this) Class(c); // perform copy-construction
- > }
- > return *this;
- > }
- >
- >In this case the constructor, destructor and copy-constructor are
- >enough to determine the copy-semantics of the class. If a deep-copy
- >is needed _you_ have to provide a suitable implementation for them.
- >BTW performing a bitwise-copy using 'memcpy' is usually a bad idea.
-
- Yeah. It's late. G'nite
-
- >
- > Enno
-
-
-